%{
#include "bison_parser.h"
#include <stdio.h>
#include <sstream>
#include <string>
#include <cstring>
#define TOKEN(name) { return SQL_##name; }
static thread_local std::stringstream strbuf;
%}

%option reentrant
%option bison-bridge
%option never-interactive
%option batch
%option noyywrap
%option nounput
%option warn
%option case-insensitive
%option bison-locations
%option header-file="flex_lexer.h"
%option outfile="flex_lexer.cpp"
%option prefix="ff_"
%s COMMENT
%x singlequotedstring

%%
"!="	TOKEN(OP_NOTEQUAL)
SIMPLE	TOKEN(SIMPLE)
TEXT	TOKEN(TEXT)
OVER	TOKEN(OVER)
BETWEEN	TOKEN(BETWEEN)
";"	TOKEN(OP_SEMI)
BIGINT	TOKEN(BIGINT)
LIMIT	TOKEN(LIMIT)
WITH	TOKEN(WITH)
ORDER	TOKEN(ORDER)
LAST	TOKEN(LAST)
UNBOUNDED	TOKEN(UNBOUNDED)
PRECEDING	TOKEN(PRECEDING)
EXCEPT	TOKEN(EXCEPT)
NUMERIC	TOKEN(NUMERIC)
"<"	TOKEN(OP_LESSTHAN)
PROCEDURE	TOKEN(PROCEDURE)
ACTION	TOKEN(ACTION)
FIRST	TOKEN(FIRST)
">="	TOKEN(OP_GREATEREQ)
CHECK	TOKEN(CHECK)
FULL	TOKEN(FULL)
NATURAL	TOKEN(NATURAL)
DOUBLE	TOKEN(DOUBLE)
NATIONAL	TOKEN(NATIONAL)
"+"	TOKEN(OP_ADD)
CURRENT	TOKEN(CURRENT)
TRIGGER	TOKEN(TRIGGER)
"-"	TOKEN(OP_SUB)
FALSE	TOKEN(FALSE)
UNIQUE	TOKEN(UNIQUE)
WHERE	TOKEN(WHERE)
MINUTE	TOKEN(MINUTE)
BEFORE	TOKEN(BEFORE)
ON	TOKEN(ON)
PARTIAL	TOKEN(PARTIAL)
OF	TOKEN(OF)
AFTER	TOKEN(AFTER)
PRIMARY	TOKEN(PRIMARY)
MONTH	TOKEN(MONTH)
DEFERRED	TOKEN(DEFERRED)
"$$"	TOKEN(OP_DOUBLE_DOLLAR)
VARYING	TOKEN(VARYING)
">"	TOKEN(OP_GREATERTHAN)
OR	TOKEN(OR)
PLPGSQL	TOKEN(PLPGSQL)
DELETE	TOKEN(DELETE)
INDEX	TOKEN(INDEX)
RETURN	TOKEN(RETURN)
"*"	TOKEN(OP_MUL)
FOREIGN	TOKEN(FOREIGN)
RESTRICT	TOKEN(RESTRICT)
FOLLOWING	TOKEN(FOLLOWING)
TIES	TOKEN(TIES)
DEC	TOKEN(DEC)
SELECT	TOKEN(SELECT)
BEGIN	TOKEN(BEGIN)
LANGUAGE	TOKEN(LANGUAGE)
DISTINCT	TOKEN(DISTINCT)
TRUE	TOKEN(TRUE)
BY	TOKEN(BY)
"%"	TOKEN(OP_MOD)
VALUES	TOKEN(VALUES)
IS	TOKEN(IS)
ROW	TOKEN(ROW)
FUNCTION	TOKEN(FUNCTION)
END	TOKEN(END)
RECURSIVE	TOKEN(RECURSIVE)
FOR	TOKEN(FOR)
UNION	TOKEN(UNION)
NULLS	TOKEN(NULLS)
UPDATE	TOKEN(UPDATE)
ELSE	TOKEN(ELSE)
RANGE	TOKEN(RANGE)
OFFSET	TOKEN(OFFSET)
INDEXED	TOKEN(INDEXED)
INSTEAD	TOKEN(INSTEAD)
NCHAR	TOKEN(NCHAR)
AND	TOKEN(AND)
REINDEX	TOKEN(REINDEX)
INITIALLY	TOKEN(INITIALLY)
YEAR	TOKEN(YEAR)
PRECISION	TOKEN(PRECISION)
FILTER	TOKEN(FILTER)
NOT	TOKEN(NOT)
VIEW	TOKEN(VIEW)
DEFFERRABLE	TOKEN(DEFFERRABLE)
REAL	TOKEN(REAL)
THEN	TOKEN(THEN)
OPTION	TOKEN(OPTION)
DEFAULT	TOKEN(DEFAULT)
GLOBAL	TOKEN(GLOBAL)
CROSS	TOKEN(CROSS)
CHAR	TOKEN(CHAR)
REFERENCES	TOKEN(REFERENCES)
"^"	TOKEN(OP_XOR)
GROUP	TOKEN(GROUP)
CASE	TOKEN(CASE)
SET	TOKEN(SET)
HOUR	TOKEN(HOUR)
NO	TOKEN(NO)
COLUMN	TOKEN(COLUMN)
LOCAL	TOKEN(LOCAL)
DROP	TOKEN(DROP)
REPLACE	TOKEN(REPLACE)
ASC	TOKEN(ASC)
","	TOKEN(OP_COMMA)
TABLE	TOKEN(TABLE)
ARRAY	TOKEN(ARRAY)
IF	TOKEN(IF)
EXTRACT	TOKEN(EXTRACT)
LEFT	TOKEN(LEFT)
OUTER	TOKEN(OUTER)
DECIMAL	TOKEN(DECIMAL)
PARTITION	TOKEN(PARTITION)
CASCADE	TOKEN(CASCADE)
ADD	TOKEN(ADD)
OTHERS	TOKEN(OTHERS)
"<="	TOKEN(OP_LESSEQ)
MATCH	TOKEN(MATCH)
ALL	TOKEN(ALL)
ROWS	TOKEN(ROWS)
JOIN	TOKEN(JOIN)
LIKE	TOKEN(LIKE)
INTEGER	TOKEN(INTEGER)
")"	TOKEN(OP_RP)
INT	TOKEN(INT)
BOOLEAN	TOKEN(BOOLEAN)
KEY	TOKEN(KEY)
EACH	TOKEN(EACH)
USING	TOKEN(USING)
RENAME	TOKEN(RENAME)
DO	TOKEN(DO)
FLOAT	TOKEN(FLOAT)
"("	TOKEN(OP_LP)
CHARACTER	TOKEN(CHARACTER)
UMINUS	TOKEN(UMINUS)
CAST	TOKEN(CAST)
GROUPS	TOKEN(GROUPS)
NULL	TOKEN(NULL)
SMALLINT	TOKEN(SMALLINT)
INSERT	TOKEN(INSERT)
TEMPORARY	TOKEN(TEMPORARY)
CONSTRAINT	TOKEN(CONSTRAINT)
CREATE	TOKEN(CREATE)
"["	TOKEN(OP_LBRACKET)
WHEN	TOKEN(WHEN)
IMMEDIATE	TOKEN(IMMEDIATE)
TO	TOKEN(TO)
EXCLUDE	TOKEN(EXCLUDE)
DAY	TOKEN(DAY)
CONFLICT	TOKEN(CONFLICT)
"]"	TOKEN(OP_RBRACKET)
EXECUTE	TOKEN(EXECUTE)
EXISTS	TOKEN(EXISTS)
INTO	TOKEN(INTO)
"/"	TOKEN(OP_DIVIDE)
CASCADED	TOKEN(CASCADED)
ISNULL	TOKEN(ISNULL)
AS	TOKEN(AS)
INNER	TOKEN(INNER)
INTERSECT	TOKEN(INTERSECT)
IN	TOKEN(IN)
"="	TOKEN(OP_EQUAL)
VARCHAR	TOKEN(VARCHAR)
ALTER	TOKEN(ALTER)
DESC	TOKEN(DESC)
FROM	TOKEN(FROM)
TEMP	TOKEN(TEMP)
UNLOGGED	TOKEN(UNLOGGED)
SECOND	TOKEN(SECOND)
WINDOW	TOKEN(WINDOW)
NOTHING	TOKEN(NOTHING)
HAVING	TOKEN(HAVING)
-?[0-9]+"."[0-9]* |
"."[0-9]* {
	yylval->fval = atof(yytext);
	return SQL_FLOATLITERAL;
	}

-?[0-9]+ {
	yylval->ival = atol(yytext);
	return SQL_INTLITERAL;
	}

\"[^\"\n]+\" {
	std::string s(yytext);
	yylval->sval = strdup(s.substr(1, s.size()-1).c_str());
	return SQL_STRINGLITERAL;
	}

[A-Za-z][A-Za-z0-9_]* {
	yylval->sval = strdup(yytext);
	return SQL_IDENTIFIER;
	}

\' {
	BEGIN singlequotedstring; strbuf = std::stringstream{}; strbuf << '\'';
	}

<singlequotedstring>\'\' {
	strbuf << '\'';
	}

<singlequotedstring>[^']* {
	strbuf << yytext;
	}

<singlequotedstring>\' {
	BEGIN 0; 
	strbuf << '\'';
	yylval->sval = strdup(strbuf.str().c_str());
	return SQL_STRINGLITERAL;
	}

<singlequotedstring><<EOF>> {
	return 0;
	}

[ \t\n]+ {
	}

. {
	return 0;
	}

%%
